
import { time } from 'console';
import { TimeLike } from 'fs';
import * as fs from 'fs/promises';
import * as http from 'http';
import * as ws from 'websocket';
// import { Operation, OperationType } from './defines';
interface Player {
    token: string
    connection: ws.connection,
}
interface Frame {
    index: number
    cmds: Operation[]
}
interface Operation {
    [key: string]: any;
}

export default class GameServer {
    private static _instance: GameServer = new GameServer();
    static get instance(): GameServer {
        new Date().getTime()
        if (!GameServer._instance) {
            GameServer._instance = new GameServer();
        }
        return GameServer._instance;
    }
    port: number = 3000;
    /**scoket */
    wsServer?: ws.server;

    httpServer!: http.Server;
    get clientList(): ws.connection[] {
        let list: ws.connection[] = [];
        if (this.wsServer) {
            list = this.wsServer.connections;
        }
        return list;
    }

    totalPlayerNum: number = 2;
    curPlayerList: Player[] = []

    totalFrames: Frame[] = []
    curFrame: Frame = { index: 0, cmds: [] }
    curFrameIdx: number = 0;
    frameRate: number = 30;
    constructor() {
        this.init();
    }
    init() {
        console.log('服务器启动...')
        const httpServer = http.createServer(function (socket) {
            // 事件名称为text(读取字符串时，就叫做text)，读取客户端传来的字符串
            socket.on('text', function (str) {
                // 在控制台输出前端传来的消息
                console.log('str', str);
                //向前端回复消息
                // socket.sendText('服务器端收到客户端端发来的消息了！' + count++);
            });
        }).listen(this.port);

        const wsServer = new ws.server({
            httpServer: httpServer,
            autoAcceptConnections: false
        });
        wsServer.on('request', this.onRequest.bind(this));

        this.httpServer = httpServer;
        this.wsServer = wsServer;
    }
    serverClose() {
        if (this.wsServer) {
            this.wsServer.connections.forEach(v => {
                v.close();
            })
        }
    }
    /**房间是否满了 */
    isPlayerFull(): boolean {
        return this.clientList.length >= this.totalPlayerNum;
    }
    tickHandler: (NodeJS.Timeout | null) = null;
    gameStart() {
        console.log('开始游戏')
        this.curFrame.index = 0;
        this.tick();
        this.tickHandler = setInterval(this.tick.bind(this), 1000 / this.frameRate)
    }
    gameOver() {
        console.log('游戏结束')
        if (this.tickHandler) {

            clearInterval(this.tickHandler)
        }
        this.tickHandler = null;
    }
    // 收集一次用户的操作，发送并缓存一帧
    tick() {
        this.boasdcast({ type: 'cmd', frame: this.curFrame });
        this.totalFrames.push(this.curFrame)
        this.curFrame.index++;
        this.curFrame.cmds = [];
    }
    /**当有请求连接 */
    onRequest(req: ws.request) {
        let Client: ws.connection;
        Client = req.accept('game', req.origin);

        /**当接收到数据 */
        Client.on('message', (message: ws.Message) => {
            // console.log(`数据： ${message}`);
            if (message.type === 'utf8') {
                let data = <Operation>JSON.parse(message.utf8Data);
                console.log(`${data.token}的数据： + ${message.utf8Data}`);
                switch (data.type) {
                    // 加入匹配
                    case 'login':
                        this.send(Client, { type: 'loginSuccess', token: data.token || this.createHash(64) })
                        break;
                    case 'match':
                        console.log('match结果', this.isPlayerFull(), this.tickHandler)
                        if (this.isPlayerFull() && !this.tickHandler) {
                            console.log('匹配成功，广播第0帧')
                            this.boasdcast({ type: 'matchSuccess' })
                            this.gameStart();
                        }
                        break
                    // 获取帧
                    case 'getAllFrames':
                        this.send(Client, { type: 'getAllFrames', token: this.totalFrames })
                        break
                    // 帧操作
                    case 'cmd':
                        // 收到指令后，存起来，定时发送
                        this.curFrame.cmds.push(data)
                        break
                }
            }
            else if (message.type === 'binary') {
                let data = <Buffer>message.binaryData;
                console.log('接收到二进制数据：' + data.length);
                Client.sendBytes(data);
            }
        });
        /**当连接断开 */
        Client.on('close', (reasonCode: any, description: any) => {
            console.log((new Date()) + '客户端断开连接：' + Client.remoteAddress, reasonCode, description);
            this.showClientCount();
        });
        this.showClientCount();
    }
    showClientCount() {
        console.log((new Date()) + '连接客户端成功,目前已连接', this.clientList.length, '个');
    }

    boasdcast(data: Operation) {
        if (this.wsServer) {
            console.log('data', this.curFrame.index, data)
            this.wsServer.broadcast(JSON.stringify(data))
        }
    }

    send(client: ws.connection, data: Operation) {
        client.send(JSON.stringify(data))
    }

    getFrameByIdx(idx: number) {
        return this.totalFrames[idx]
    }

    createHash(hashLength: number) {
        // 默认长度 24
        return Array.from(Array(Number(hashLength) || 24), () => Math.floor(Math.random() * 36).toString(36)).join('');
    }



    createRoom() {

    }
}


// let list;
// list = document.getElementsByClassName('be-dropdown-menu menu-align-');
// let success = false
// setInterval(() => {
//     success = false;
//     for (let i = 0; i < list.length; i++) {
//         let v = list[i]
//         if (v && v.children[1] && v.children[1].innerText.match('取消关注')) {
//             success = true;
//             return v.children[1].click()
//         }
//     }
//     if (!success) {
//         let next = document.getElementsByClassName('be-pager-next');
//         if (next) {
//             next[0].click()
//         }
//     }
// }, 500)